package thread.demo10.WaitAndNotify;

/**
 * 等待唤醒案例：线程之间的通信
 *      创建一个顾客线程（消费者）：告知老板要的包子的种类和数量，调用wait方法，放弃cpu的执行时间片，进入到waiting状态（无限等待）
 *      创建一个老板线程（生产者）：花五秒做包子，做好包子之后，调用notify方法，唤醒顾客吃包子
 *
 *      注意事项：
 *          顾客和老板必须使用同步代码块包裹起来，保证等待和唤醒只有一个在执行
 *          同步使用的对象锁必须保证唯一
 *          只有锁对象才能调用wait和notify方法
 *      Object类中的方法
 *      void wait（）
 *          放弃cpu执行权，等待其他线程调用此对象的notify或nofityAll方法 唤醒此线程 ，否则一直等待
 *      void notify()
 *          唤醒在此对象监视器（对象锁）上等待的单个线程 ，被唤醒的线程继续执行wait方法后的代码
 *          notifyAll唤醒所有等待的线程
 */
public class Demo01WaitAndNotify {
    public static void main(String[] args) {
        //创建锁对象
        Object obj = new Object();

        new Thread(){
            @Override
            public void run() {
                //保证等待和唤醒的线程只有一个在执行，需要使用同步技术
                //synchronized (obj) {
                    while (true) {
                        synchronized(obj){
                        System.out.println("告知老板需要的包子种类与数量");
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("顾客开吃");
                            try {
                                Thread.sleep(2000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println("------------------");
                        }
                    }
                //}
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (obj){
                        //生产包子花了3秒
                        /*
                            try {
                                Thread.sleep(3000);
                             } catch (InterruptedException e) {
                             e.printStackTrace();
                             }
                         */
                        System.out.println("3秒之后，包子做好了，老板告知顾客，可以干饭了");
                        obj.notify();
                    }
                }
            }
        }.start();
    }
}
